//
//  TokenProtocol.m
//  TabulaImaginarium9
//
//  Created by TA2 on 6/16/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "TokenProtocol.h"

@implementation TokenProtocol

@synthesize tokenView;

- (void)dealloc {
    [tokenView release];
    tokenView = nil;
    [super dealloc];
}

- (void)readPacket:(NSArray *)packet fromSocket:(AsyncSocket *)socket {
	NSArray *arguments = packet;
    /*NSLog(stringTag);
    if ([arguments count] > 1) { NSLog([arguments objectAtIndex:1]);}
    if ([arguments count] > 2) { NSLog([arguments objectAtIndex:2]);}
    if ([arguments count] > 3) { NSLog([arguments objectAtIndex:3]);}
    if ([arguments count] > 4) { NSLog([arguments objectAtIndex:4]);}
    if ([arguments count] > 5) { NSLog([arguments objectAtIndex:5]);}
    if ([arguments count] > 6) { NSLog([arguments objectAtIndex:6]);}
    if ([arguments count] > 7) { NSLog([arguments objectAtIndex:7]);}*/
	if ([arguments count] > 1) {
		if ([[arguments objectAtIndex:1] isEqualToString:@"ST"]) {
			if ([Players sharedLocalPlayer].isHost) {
				[[NetworkController sharedNetworkController] sendDataToAll:[NetworkController argumentArrayToData:arguments] withTag:0 butSocket:socket];
			}
			NSString *path = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:[(NSString *)[arguments objectAtIndex:2] lastPathComponent]];
			if ([[LoadedImages sharedLoadedImages].images objectForKey:path]) {
				NSArray *tiledImages = [[LoadedImages sharedLoadedImages].tiledTokenImages objectForKey:path];
				if (!tiledImages) {
					UIImage *image = [[LoadedImages sharedLoadedImages].images objectForKey:path];
					NSArray *tokenArguments = [path componentsSeparatedByCharactersInSet:
											   [NSCharacterSet characterSetWithCharactersInString:@"_"]];
					tiledImages = [Token tileImage:image withWidth:[[tokenArguments objectAtIndex:[tokenArguments count] - 1] intValue] withHeight:[[[tokenArguments objectAtIndex:[tokenArguments count] - 2] stringByDeletingPathExtension] intValue]];
					[[LoadedImages sharedLoadedImages].tiledTokenImages setObject:tiledImages forKey:path];
				}
				NSString *tokenId = [arguments objectAtIndex:6];
				Token *newToken = [[[Token alloc] initWithImageArray:tiledImages withId:tokenId] autorelease];
                newToken.protocolId = stringTag;
				newToken.tokenImagePath = path;
				
				[newToken setOrigin:(CGPoint){[[arguments objectAtIndex:3] intValue], [[arguments objectAtIndex:4] intValue]}];
				NSMutableArray *points = [newToken getPointsWithOffset:0];
				for (NSValue *pointValue in points) {
					CGPoint point = [pointValue CGPointValue];
					[tokenView.map addToken:newToken atPoint:point withTileSize:tokenView.tileSize];
					[tokenView setNeedsDisplayInRect:(CGRect){(CGPoint){point.x*tokenView.tileSize.width, point.y*tokenView.tileSize.height}, (CGSize){tokenView.tileSize.width, tokenView.tileSize.height}}];
				}
                [tokenView.map setId:[[arguments objectAtIndex:5] intValue] forProtocolId:stringTag];
			}
		} else if ([[arguments objectAtIndex:1] isEqualToString:@"DT"]) {
			if ([Players sharedLocalPlayer].isHost) {
				[[NetworkController sharedNetworkController] sendDataToAll:[NetworkController argumentArrayToData:arguments] withTag:0 butSocket:socket];
			}
			NSArray *points = [tokenView.map removeToken:[arguments objectAtIndex:2]];
			if (points) {
				for (NSValue *pointValue in points) {
					CGPoint point = [pointValue CGPointValue];
					[tokenView setNeedsDisplayInRect:(CGRect){(CGPoint){point.x*tokenView.tileSize.width, point.y*tokenView.tileSize.height}, (CGSize){tokenView.tileSize.width, tokenView.tileSize.height}}];
				}
			}
		} else if ([[arguments objectAtIndex:1] isEqualToString:@"SMT"]) {
			BOOL validTokenMove = YES;
            @synchronized (tokenView.map.currentlyMovingTokenLock) {
                for (Player *player in [Players sharedAllPlayers]) {
                    if (player.currentlyMovingToken) {
                        if ([player.currentlyMovingToken.tokenId isEqualToString:[arguments objectAtIndex:5]]) {
                            if (player == [Players sharedLocalPlayer]) {
                                if (!player.isHost) {
                                    CGPoint point = (CGPoint){[[arguments objectAtIndex:2] intValue], [[arguments objectAtIndex:3] intValue]};
                                    NSMutableArray *oldPoints = [player.currentlyMovingToken getPointsWithOffset:0];
                                    [player.currentlyMovingToken setOrigin:point];
                                    [tokenView.map addToken:player.currentlyMovingToken atPoint:point withTileSize:tokenView.tileSize];
                                    player.currentlyMovingToken = nil;
                                    for (NSValue *pointValue in oldPoints) {
                                        CGPoint point = [pointValue CGPointValue];
                                        [tokenView setNeedsDisplayInRect:(CGRect){(CGPoint){point.x*tokenView.tileSize.width, point.y*tokenView.tileSize.height}, (CGSize){tokenView.tileSize.width, tokenView.tileSize.height}}];
                                    }
                                } else {
                                    validTokenMove = NO;
                                }
                            } else {
                                validTokenMove = NO;
                            }
                        }
                    }
                }
                if (validTokenMove) {
                    if ([Players sharedLocalPlayer].isHost) {
                        [[NetworkController sharedNetworkController] sendDataToAll:[NetworkController argumentArrayToData:arguments] withTag:0 butSocket:socket];
                    }
                    for (Player *player in [Players sharedPlayers]) {
                        if ([player.ip isEqualToString:[arguments objectAtIndex:4]]) {
                            if (!player.currentlyMovingToken) {
                                CGPoint point = (CGPoint){[[arguments objectAtIndex:2] intValue], [[arguments objectAtIndex:3] intValue]};
                                Token *token = [tokenView.map tokenForPoint:point withViewId:stringTag];
                                if ([token.tokenId isEqualToString:[arguments objectAtIndex:5]]) {
                                    [token enterMovingMode:point];
                                    NSMutableArray *points = [token getPointsWithOffset:0];
                                    for (NSValue *pointValue in points) {
                                        CGPoint point = [pointValue CGPointValue];
                                        [tokenView.map removeToken:token fromPoint:point];
                                        [tokenView setNeedsDisplayInRect:(CGRect){(CGPoint){point.x*tokenView.tileSize.width, point.y*tokenView.tileSize.height}, (CGSize){tokenView.tileSize.width, tokenView.tileSize.height}}];       
                                    }
                                    player.currentlyMovingToken = token;
                                }
                            }
                        }
                    }
                }
            }	
		} else if ([[arguments objectAtIndex:1] isEqualToString:@"MMT"]) {
			if ([Players sharedLocalPlayer].isHost) {
				[[NetworkController sharedNetworkController] sendDataToAll:[NetworkController argumentArrayToData:arguments] withTag:0 butSocket:socket];
			}
            @synchronized(tokenView.map.currentlyMovingTokenLock) {
                for (Player *player in [Players sharedPlayers]) {
                    if ([player.ip isEqualToString:[arguments objectAtIndex:4]]) {
                        if (player.currentlyMovingToken) {
                            CGPoint point = (CGPoint){[[arguments objectAtIndex:2] intValue], [[arguments objectAtIndex:3] intValue]};
                            if (!CGPointEqualToPoint([player.currentlyMovingToken getOrigin], point)) {
                                NSMutableArray *points = [player.currentlyMovingToken getPointsWithOffset:0];
                                for (NSValue *pointValue in points) {
                                    CGPoint point = [pointValue CGPointValue];
                                    [tokenView setNeedsDisplayInRect:(CGRect){(CGPoint){point.x*tokenView.tileSize.width, point.y*tokenView.tileSize.height}, (CGSize){tokenView.tileSize.width, tokenView.tileSize.height}}];
                                }
                                [player.currentlyMovingToken setOrigin:point];
                                points = [player.currentlyMovingToken getPointsWithOffset:0];
                                for (NSValue *pointValue in points) {
                                    CGPoint point = [pointValue CGPointValue];
                                    [tokenView setNeedsDisplayInRect:(CGRect){(CGPoint){point.x*tokenView.tileSize.width, point.y*tokenView.tileSize.height}, (CGSize){tokenView.tileSize.width, tokenView.tileSize.height}}];
                                }
                            }
                        }
                    }
                }
            }
		} else if ([[arguments objectAtIndex:1] isEqualToString:@"PMT"]) {
			if ([Players sharedLocalPlayer].isHost) {
				[[NetworkController sharedNetworkController] sendDataToAll:[NetworkController argumentArrayToData:arguments] withTag:0 butSocket:socket];
			}
            @synchronized(tokenView.map.currentlyMovingTokenLock) {
                CGPoint point = (CGPoint){[[arguments objectAtIndex:2] intValue], [[arguments objectAtIndex:3] intValue]};
                for (Player *player in [Players sharedPlayers]) {
                    if ([player.ip isEqualToString:[arguments objectAtIndex:4]]) {
                        if (player.currentlyMovingToken) {
                            Token *token = player.currentlyMovingToken;
                            player.currentlyMovingToken = nil;
                            NSMutableArray *points = [token getPointsWithOffset:1];
                            for (NSValue *pointValue in points) {
                                CGPoint point = [pointValue CGPointValue];
                                [tokenView setNeedsDisplayInRect:(CGRect){(CGPoint){point.x*tokenView.tileSize.width, point.y*tokenView.tileSize.height}, (CGSize){tokenView.tileSize.width, tokenView.tileSize.height}}];
                                
                            }
                            [token setOrigin:point];
                            points = [token getPointsWithOffset:0];
                            for (NSValue *pointValue in points) {
                                CGPoint point = [pointValue CGPointValue];
                                [tokenView.map addToken:token atPoint:point withTileSize:tokenView.tileSize];
                                [tokenView setNeedsDisplayInRect:(CGRect){(CGPoint){point.x*tokenView.tileSize.width, point.y*tokenView.tileSize.height}, (CGSize){tokenView.tileSize.width, tokenView.tileSize.height}}];
                            }
                            [token leaveMovingMode];
                        }
                    }
                }
            }
		} else if ([[arguments objectAtIndex:1] isEqualToString:@"RT"]) {
			CGPoint point = (CGPoint){[[arguments objectAtIndex:2] intValue], [[arguments objectAtIndex:3] intValue]};
			NSArray *tokens = [tokenView.map tokenStackForPoint:point];
			for (Token *token in tokens) {
                if ([token.protocolId isEqualToString:stringTag]) {
                    NSString *path = token.tokenImagePath;
                    if (path) {
                        if ([token getImageAtPoint:point withOffset:0] == (CGLayerRef)([((NSMutableArray *)[token.tiledImages objectAtIndex:0]) objectAtIndex:0])) {
                            [self sendToken:path atPoint:point withId:token.tokenId toSocket:socket];
                        }
                    }
                }
			}
		} else if ([[arguments objectAtIndex:1] isEqualToString:@"RAT"]) {
			NSArray *modifiedTiles = [tokenView.map getAllModifiedTilePoints];
			for (NSValue *pointValue in modifiedTiles) {
				CGPoint point = [pointValue CGPointValue];
				NSArray *tokens = [tokenView.map tokenStackForPoint:point];
				for (Token *token in tokens) {
                    if ([token.protocolId isEqualToString:stringTag]) {
                        NSString *path = token.tokenImagePath;
                        if (path) {
                            if ([token getImageAtPoint:point withOffset:0] == (CGLayerRef)([((NSMutableArray *)[token.tiledImages objectAtIndex:0]) objectAtIndex:0])) {
                                [self sendToken:path atPoint:point withId:token.tokenId toSocket:socket];
                            }
                        }
                    }
				}
			}
			for (Player *player in [Players sharedAllPlayers]) {
				if (player.currentlyMovingToken) {
					[self sendToken:player.currentlyMovingToken.tokenImagePath atPoint:[player.currentlyMovingToken getOrigin] withId:player.currentlyMovingToken.tokenId toSocket:socket];
					[self startMovingToken:[player.currentlyMovingToken getOrigin] withId:player.currentlyMovingToken.tokenId];
				}
			}
		} 
	}
}

- (void)sendToken:(NSString *)path atPoint:(CGPoint)point withId:(NSString *)tokenId {
	//ST: Send token
	NSString *dataString = [[[stringTag stringByAppendingString:[[[@"|ST|" stringByAppendingString:path] stringByAppendingString:@"|"] 
                                                                 stringByAppendingString:[NSString stringWithFormat:@"%f|%f|%d|", point.x, point.y, [tokenView.map getId:stringTag]]]] stringByAppendingString:tokenId] stringByAppendingString:@"|≤|"];
	NSData *data = [dataString dataUsingEncoding: NSUTF8StringEncoding];
	[[NetworkController sharedNetworkController] sendDataToAll:data withTag:0];
}

- (void)sendToken:(NSString *)path atPoint:(CGPoint)point withId:(NSString *)tokenId toSocket:(AsyncSocket *)socket {
	//ST: Send token
	NSString *dataString = [[[stringTag stringByAppendingString:[[[@"|ST|" stringByAppendingString:path] stringByAppendingString:@"|"] 
																stringByAppendingString:[NSString stringWithFormat:@"%f|%f|%d|", point.x, point.y, [tokenView.map getId:stringTag]]]] stringByAppendingString:tokenId] stringByAppendingString:@"|≤|"];
	NSData *data = [dataString dataUsingEncoding: NSUTF8StringEncoding];
	[[NetworkController sharedNetworkController] sendData:data toSocket:socket withTag:0];
}

- (void)deleteToken:(NSString *)tokenId {
	//DT: Delete token
	NSString *dataString = [stringTag stringByAppendingString:[[@"|DT|" stringByAppendingString:tokenId] stringByAppendingString:@"|≤|"]];
	NSData *data = [dataString dataUsingEncoding: NSUTF8StringEncoding];
	[[NetworkController sharedNetworkController] sendDataToAll:data withTag:0];
}

- (void)startMovingToken:(CGPoint)point withId:(NSString *)tokenId {
	//SMT: Start moving token
	NSString *dataString = [[[[[[stringTag stringByAppendingString:@"|SMT|"] stringByAppendingString:[NSString stringWithFormat:@"%f|%f|", point.x, point.y]] stringByAppendingString:[Players sharedLocalPlayer].ip] stringByAppendingString:@"|"] stringByAppendingString:tokenId] stringByAppendingString:@"|≤|"];
	NSData *data = [dataString dataUsingEncoding: NSUTF8StringEncoding];
	[[NetworkController sharedNetworkController] sendDataToAll:data withTag:0];
}

- (void)moveMovingToken:(CGPoint)point {
	//MMT: Move moving token
	NSString *dataString = [[[[stringTag stringByAppendingString:@"|MMT|"] stringByAppendingString:[NSString stringWithFormat:@"%f|%f|", point.x, point.y]] stringByAppendingString:[Players sharedLocalPlayer].ip] stringByAppendingString:@"|≤|"];
	NSData *data = [dataString dataUsingEncoding: NSUTF8StringEncoding];
	[[NetworkController sharedNetworkController] sendDataToAll:data withTag:0];
}

- (void)placeMovingToken:(CGPoint)point {
	//PMT: Place moving token
	NSString *dataString = [[[[stringTag stringByAppendingString:@"|PMT|"] stringByAppendingString:[NSString stringWithFormat:@"%f|%f|", point.x, point.y]] stringByAppendingString:[Players sharedLocalPlayer].ip] stringByAppendingString:@"|≤|"];
	NSData *data = [dataString dataUsingEncoding: NSUTF8StringEncoding];
	[[NetworkController sharedNetworkController] sendDataToAll:data withTag:0];
}

- (void)sendRequestForTokenAtPoint:(CGPoint)point {
	//RT: Request modified token
	NSString *dataString = [[stringTag stringByAppendingString:[@"|RT|" stringByAppendingString:[NSString stringWithFormat:@"%f|%f", point.x, point.y]]] stringByAppendingString:@"|≤|"];
	NSData *data = [dataString dataUsingEncoding: NSUTF8StringEncoding];
	[[NetworkController sharedNetworkController] sendDataToAll:data withTag:0];
}

- (void)sendRequestForAllTokens {
	//RAT: Request all tokens
	NSString *dataString = [[stringTag stringByAppendingString:@"|RAT"] stringByAppendingString:@"|≤|"];
	NSData *data = [dataString dataUsingEncoding: NSUTF8StringEncoding];
	[[NetworkController sharedNetworkController] sendDataToAll:data withTag:0];
}

- (void)setupProtocol {
	if (![Players sharedLocalPlayer].isHost) {
		[self sendRequestForAllTokens];
	}
}

@end
